﻿
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using System.Windows.Forms ;
using System.Data ;

using MskEdit.Msk.Model ;
using MskEdit.Msk.Frontend ;
using MskEdit.Dxf.Model ;
using MskEdit.Dxf.Frontend ;


namespace MskEdit.Frontend {

    public partial class MskMainForm : Form {
    
        #region Private data
        
        private bool            showsMskGridLines_ ;
        private MskProperties   mskProperties_ ;
        
        #endregion
        
        #region Private operations
                
        private void HandlePageSelectionChanged( string pageKeyAsString ) {
        
            var mskPageKey = MskPageKey.TryFrom( pageKeyAsString, null ) ;
            if ( mskPageKey == null )
                return ;
                
            mskProperties_.MskPageKey = mskPageKey ;
        }
                
/*        
        private void HandleMskLineSelected( ProgramComponents programComponents, MskMainForm mskMainForm, MskLineKey anyMskLineKey ) {
            
            var mskLine = programComponents.tryGetMskLine( anyMskLineKey, MskLine.NullLine ) ;
            var anyDxfAttrDataTable = programComponents.tryGetDxfAttrDataTable( mskLine.AcadBlock, mskLine.AcadTag, null ) ;

            mskProperties_.MskLine = mskLine ;
            showAnyDxfAttrDataTable( anyDxfAttrDataTable ) ;
        }
*/
        #endregion
        
        #region Public events
                        
        public delegate void EditProgramSettingsRequestEventHandler();
        public event EditProgramSettingsRequestEventHandler EditProgramSettingsRequested;

        public delegate void ProjectSelectedEventHandler( string projectDirectoryName ) ;
        public event ProjectSelectedEventHandler ProjectSelected ;

        public delegate void SaveMskFileRequestEventHandler() ;
        public event SaveMskFileRequestEventHandler SaveMskFileRequested ;
    
        public delegate void ApplicationExitRequestEventHandler() ;
        public event ApplicationExitRequestEventHandler ApplicationExitRequested ;
    
        public delegate void MskLineContentChangedEventHandler( MskLine mskLine ) ;
        public event MskLineContentChangedEventHandler MskLineContentChanged ;

        #endregion
        
        #region Public callouts

        public delegate DataTable ProjectsTableCallout() ;
        public ProjectsTableCallout CalloutForProjectsTable ;

        public delegate MskLine MskLineCallout( MskLineKey mskLineKey, MskLine fallbackValue ) ;
        public MskLineCallout CalloutForMskLine ;

        public delegate DxfAttrDataTable DxfAttrDataTableCallout( string acadBlock, string acadTag, DxfAttrDataTable fallbackValue  ) ;
        public DxfAttrDataTableCallout CalloutForDxfAttrDataTable ;
        
        #endregion

        #region Public properties
        
        public bool ShowsMskGridLines {
            get { return showsMskGridLines_ ; }
            set { HandleVisibleGridLinesChanged( value ) ; }
        }

        #endregion

        #region Public foundation

        public MskMainForm() {
        
            // Components
            InitializeComponent() ;
            
            // Msk properties
            mskProperties_ = new MskProperties() ;
            this.combinedPropertyGrid.SelectedObject = mskProperties_ ;
            
            mskProperties_.PropertiesChanged += () => 
                this.combinedPropertyGrid.Refresh() ;
                
            mskProperties_.LineContentChanged += ( MskLine mskLine ) => 
                HandleMskLineContentChanged( mskLine ) ;

        }
 
        #endregion

        #region Public operations

        public void showAnyDxfDocuments( DxfDocument[] anyDxfDocuments ) {
        
            dxfTreeView.BeginUpdate() ;            
            dxfTreeView.Nodes.Clear() ;
            
            if ( ( anyDxfDocuments != null ) && ( anyDxfDocuments.Length > 0 ) ) {
                foreach ( DxfDocument dxfDocument in anyDxfDocuments )
                    dxfTreeView.Nodes.Add( new DxfDocumentTreeNode( dxfDocument ) ) ;
            }
            
            dxfTreeView.EndUpdate() ;
        }


        public void showAnyMskDocument( MskDocument anyMskDocument, bool showGridLines ) {
            
            this.PageTabControl.TabPages.Clear() ;
            
            if ( anyMskDocument == null ) {
                this.Text = "MskEdit - " + "<No Msk document>" ;
                mskProperties_.MskFileName = "" ;                
            }
            else {
                this.Text = "MskEdit - " + anyMskDocument.DocumentName ;
                mskProperties_.MskFileName = anyMskDocument.DocumentName ;
                
                var fieldGeometer = MskFieldGeometerFactory.createFrom( this ) ;
                var pageKeys = anyMskDocument.PageKeys ;
                
                foreach ( var pageKey in pageKeys ) {
                    var mskPage = anyMskDocument.getPageWith( pageKey ) ;
                    var mskTabPage = MskTabPage.From( mskPage, fieldGeometer, showGridLines ) ; 
                    
                    this.PageTabControl.TabPages.Add( mskTabPage ) ; 
                    mskTabPage.LineSelectionChanged += HandleSelectedMskLineChanged ;
                }
            }
        }
        

        public void showAnyDxfAttrDataTable( DxfAttrDataTable anyDxfAttrDataTable ) {
            this.attrDataGridView.DataSource = anyDxfAttrDataTable ;
        }

        #endregion

        #region Private event handlers
        
        private void HandleVisibleGridLinesChanged( bool showGridLines ) {
        
            showsMskGridLines_  = showGridLines ;
            
            foreach ( MskTabPage mskTabPage in this.PageTabControl.TabPages )
                mskTabPage.MskPagePanel.HasVisibleGrid = showGridLines ;
        }
        
        
        private void HandlePropertiesToolStripMenuItemClick(object sender, EventArgs e) {
            if ( EditProgramSettingsRequested != null )
                EditProgramSettingsRequested.Invoke();
        }


        private void HandleSelectedMskLineChanged( MskLineKey anyMskLineKey ) {
                
            MskLine mskLine = MskLine.NullLine ;
            if ( (CalloutForMskLine != null) && ( anyMskLineKey != null ) )
                mskLine = CalloutForMskLine( anyMskLineKey, MskLine.NullLine ) ;
                
            DxfAttrDataTable anyDxfAttrDataTable = null ;
            if ( CalloutForDxfAttrDataTable != null )
                anyDxfAttrDataTable = CalloutForDxfAttrDataTable( mskLine.AcadBlock, mskLine.AcadTag, null ) ;

            mskProperties_.MskLine = mskLine ;
            showAnyDxfAttrDataTable( anyDxfAttrDataTable ) ;

        }
        
        
        private void HandleMskLineContentChanged( MskLine mskLine ) {        
            if ( MskLineContentChanged != null )
                MskLineContentChanged.Invoke( mskLine ) ;
            
            foreach ( MskTabPage mskTabPage in this.PageTabControl.TabPages )
                mskTabPage.updateMskLine( mskLine ) ;
        }


        private void HandleMskMainFormLoad( object sender, EventArgs e ) {      
            updateProjectsTable() ;
        }

        private void HandleSaveMskToolStripMenuItemClick( object sender, System.EventArgs e ) {        
            if ( SaveMskFileRequested != null )
                SaveMskFileRequested.Invoke() ;            
        }


        private void HandleExitToolStripMenuItemClick( object sender, EventArgs e ) {        
            if ( ApplicationExitRequested != null )
                ApplicationExitRequested.Invoke() ;
        }
        
        
        private void HandlePageTabControlSelectedIndexChanged( object sender, EventArgs e ) {
        
            if ( this.PageTabControl.SelectedTab != null )
                HandlePageSelectionChanged( this.PageTabControl.SelectedTab.Text ) ;
                
            HandleSelectedMskLineChanged( null ) ;
        }
        
        
        private void HandlePageTabControlControlAdded( object sender, ControlEventArgs e ) {
        
            if ( this.PageTabControl.SelectedTab != null )
                HandlePageSelectionChanged( this.PageTabControl.SelectedTab.Text ) ;
                
            HandleSelectedMskLineChanged( null ) ;
        }

        
        private void HandleProjectsComboBoxSelectedIndexChanged(object sender, EventArgs e) {
        
            var projectsComboBox  = sender as ComboBox ;     
           	var projectsDataTable = projectsComboBox.DataSource as DataTable ;
           	
           	if ( projectsDataTable == null )
           	    return ;
             
            string projectDirectoryName = projectsDataTable.Rows[projectsComboBox.SelectedIndex]["QDIR"] as string ;
            
            if ( String.IsNullOrEmpty( projectDirectoryName ) )
                return ;
                    	
            if ( ProjectSelected != null )                        
                ProjectSelected.Invoke( projectDirectoryName );
            
            HandleSelectedMskLineChanged( null ) ;
        }

        #endregion

        #region Private operations

        private void updateProjectsTable() {
        
            DataTable projectsTable = ( CalloutForProjectsTable != null ) 
                ? CalloutForProjectsTable() 
                : null ;
        
            if (projectsTable == null)
                return;
            
            projectsComboBox.DataSource     = projectsTable;
            projectsComboBox.ValueMember    = projectsTable.Columns["QDIR"].ColumnName;
            projectsComboBox.DisplayMember  = projectsTable.Columns["PNAME_msk"].ColumnName;
        }
 
        #endregion
    }
}
